package com.sky.config;

import com.sky.interception.JwtAdminInterception;
import com.sky.interception.JwtUserInterception;
import com.sky.json.JacksonObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;

import java.util.List;

@Configuration
@Slf4j
public class WebMvcConfiguration extends WebMvcConfigurationSupport {
    @Autowired
    private JwtAdminInterception jwtAdminInterception;
    @Autowired
    private JwtUserInterception jwtUserInterception;

    // 注册拦截器
    @Override
    protected void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(jwtAdminInterception)
                //拦截/admin下的所有请求
                .addPathPatterns("/admin/**")
                //排除/admin/employee/login请求,即登录请求
                .excludePathPatterns("/admin/employee/login");


        registry.addInterceptor(jwtUserInterception)
                .addPathPatterns("/user/**")
                .excludePathPatterns("/user/user/login")
                .excludePathPatterns("/user/shop/status");
    }

    /**
     * 生成接口文档，两步：new ApiInfo描述文档的基本信息
     * 2.new Docket描述文档的详细信息，包括要扫描的包、标题、描述、版本等信息
     *
     * @return
     */
    @Bean
    public Docket docket1() {
        log.info("準備生成接口文檔...");
        ApiInfo apiInfo = new ApiInfoBuilder()
                .title("蒼穹外賣管理系統API")
                .description("蒼穹外賣管理系統API")
                .version("1.0")
                .build();

        Docket docket = new Docket(DocumentationType.SWAGGER_2)
                .groupName("管理端")
                .apiInfo(apiInfo)
                .select()
                //指定要扫描的包
                .apis(RequestHandlerSelectors.basePackage("com.sky.controller.admin"))
                .build();
        return docket;
    }

    @Bean
    public Docket docket2() {
        ApiInfo apiInfo = new ApiInfoBuilder()
                .title("蒼穹外賣管理系統API")
                .description("蒼穹外賣管理系統API")
                .version("1.0")
                .build();

        Docket docket2 = new Docket(DocumentationType.SWAGGER_2)
                .groupName("用戶端")
                .apiInfo(apiInfo)
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.sky.controller.user"))
                .build();

        return docket2;

    }


    /**
     * 静态资源映射,访问地址：http://localhost:8080/doc.html会自动映射到Swagger2帮我们生成的API文档页面，
     * 固定在classpath:/META-INF/resources/webjars包下
     */
    @Override
    protected void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/");
        registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
    }

    /**
     * ，这个类扩展了 Spring MVC 的消息转换器
     *
     * @param converters
     */
    protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        //这里创建了一个 MappingJackson2HttpMessageConverter 的实例。这个转换器是 Spring 提供的，
        // 主要用于将 Java 对象转换为 JSON 格式，并将 JSON 数据转换为 Java 对象。
        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();

        //将一个自定义的 JacksonObjectMapper 设置为转换器的 ObjectMapper。
        // 这允许开发者定制 JSON 的序列化和反序列化行为，比如处理日期格式、字段命名策略等
        converter.setObjectMapper(new JacksonObjectMapper());
        //将刚创建并配置好的转换器添加到 converters 列表的第一个位置。这样做会确保在进行消息转换时优先使用这个自定义的转换器。
        converters.add(0, converter);
    }
}
